NestedScrolling常用在嵌套滚动的场景,比较常见的是使用CoordinateLayout实现比较炫酷的联合滚动效果,其内部也是借助了NestedScrollingChild和NestedScrollingParent这套机制。
NestedScrollingChild和NestedScrollingParent
NestedScrollingChild | NestedScrollingParent |
---|---|
startNestedScroll | onStartNestedScroll |
dispatchNestedPreScroll | onNestedPreScroll |
dispatchNestedScroll | onNestedScroll |
dispatchNestedPreFling | onNestedPreFling |
dispatchNestedFling | onNestedFling |
stopNestedScroll | onStopNestedScroll |
NestedScrollingChild接口中的方法均为主动方法,需要我们在实现类中主动调用,而NestedScrollingParent的方法基本都是回调方法。这也是NestedScrolling机制的一个体现,子View作为NestedScrolling事件传递的主动方,父View作为接收方。父View决定是移动子View控件,还是把移动偏移量交给子View,让其滚动内容。
NestedScrolling事件传递过程:
子View的事件处理过程都在onTouchEvent()。
- 子View在action down中执行startNestedScroll()启动联动流程,并设置滚动的方向;
- 父View在onStartNestedScroll()中根据传来的方向,决定是否联动,返回结果;
- 子View在action move中计算移动偏移量,执行dispatchNestedPreScroll(),将偏移情况告诉父View;
- 父View在onNestedPreScroll()中接收子View传来的偏移量,计算需要消耗的偏移量,即移动子View的距离;
- 子View计算父View消费后剩下的偏移量,在这个余量基础上计算子View还能消费多少,并把消费情况通过dispatchNestedScroll()告诉父View;
- 父View在onNestedScroll()中根据偏移量进行相应处理;
- 事件结束,子View在action up中执行stopNestedScroll()结束联动流程,父View的onStopNestedScroll()得到响应,事件传递完成。
上述联动过程的传递,通过NestedScrollingChildHelper和NestedScrollingParentHelper这爷俩就可简单实现,里面封装了很多实现细节,让我们开发过程更高效。
fling过程和上述相同,可以通过示例代码了解。
下面通过代码讲一讲上述流程:
1 | class ChildView implements NestedScrollingChild { |
1 | class ParentView implements NestedScrollParent { |
相关问题:
1.子View主动触发一个事件,父View的对应方法就能响应,那父子View的联动关系是如何确定的?
看下NestScrollingChildHelper#startNestedScroll()的实现。
1 | public boolean startNestedScroll(int axes) { |
相关知识点:
1.View#canScrollVertically()
判断View在垂直方向是否可以上下滚动。
其中:
View#canScrollVertically(1),return true ——可以向上滚动,反之,不可以
View#canScrollVertically(-1),return true ——可以向下滚动,反之,不可以
2.View#computeVerticalScrollOffset()
判断View的内容在垂直方向上滚动的距离。返回值:0~***,均为正值。
比如WebView,起始状态为0,内容向上滚动后,为某个正值。
3.View#computeVerticalScrollRange()
View内容的总高度。
4.View#computeVerticalScrollExtent()
View在屏幕区域内显示的高度。